package xyz.xtt.asset.controller;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Maps;
import com.google.common.primitives.Longs;

import cn.hutool.json.JSONUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import xyz.xtt.asset.api.enums.AssetTypeEnum;
import xyz.xtt.asset.client.request.CancelTransactionRequest;
import xyz.xtt.asset.client.request.CardInfoRequest;
import xyz.xtt.asset.client.request.ConfirmTransactionRequest;
import xyz.xtt.asset.client.request.DeliverRequest;
import xyz.xtt.asset.client.request.MakeTransactionRequest;
import xyz.xtt.asset.client.request.ThirdOrderRequest;
import xyz.xtt.asset.client.response.AssetAllInfoResponse;
import xyz.xtt.asset.client.response.AssetDetailInfo;
import xyz.xtt.asset.client.response.AssetExtInfoResponse;
import xyz.xtt.asset.client.response.AssetNoResponse;
import xyz.xtt.asset.client.response.AssetUserLogResponse;
import xyz.xtt.asset.client.response.AssetVo;
import xyz.xtt.asset.client.response.BlindBoxDetailResponse;
import xyz.xtt.asset.client.response.CancelOrderResponse;
import xyz.xtt.asset.client.response.ConfirmOrderResponse;
import xyz.xtt.asset.client.response.MintResponse;
import xyz.xtt.asset.client.response.TblAssetCardDto;
import xyz.xtt.asset.entity.TblAssetCard;
import xyz.xtt.asset.entity.TblAssetTransaction;
import xyz.xtt.asset.entity.TblAssetUserLog;
import xyz.xtt.asset.service.ICmpService;
import xyz.xtt.asset.service.INftService;
import xyz.xtt.asset.service.IRoseService;
import xyz.xtt.asset.service.ITblAssetAccountService;
import xyz.xtt.asset.service.ITblAssetCardService;
import xyz.xtt.asset.service.ITblAssetExtService;
import xyz.xtt.asset.service.ITblAssetNoService;
import xyz.xtt.asset.service.ITblAssetService;
import xyz.xtt.asset.service.ITblAssetUserLogService;
import xyz.xtt.asset.service.ITblBlindBoxDetailService;
import xyz.xtt.asset.vo.BusinessAttachVo;
import xyz.xtt.common.objects.DozerUtil;
import xyz.xtt.common.response.ApiResult;
import xyz.xtt.pay.client.response.TblPayOrderDto;

@Tag(name = "资产管理对外服务接口", description = "资产管理对外服务接口")
@RefreshScope
@Slf4j
@RequestMapping("/api/nft/asset")
@RestController
public class InnerAssetController {
	@Autowired
	private ITblAssetService iTblAssetService;
	@Autowired
	private ITblAssetAccountService iTblAssetAccountService;
	@Autowired
	private ITblBlindBoxDetailService iTblBlindBoxDetailService;
	@Autowired
	private ITblAssetUserLogService iTblAssetUserLogService;
	@Autowired
	private ITblAssetExtService iTblAssetExtService;
	@Autowired
	private IRoseService iRoseService;
	@Autowired
	private INftService iNftService;
	@Autowired
	private StringRedisTemplate stringRedisTemplate;
	@Autowired
	private ITblAssetCardService iTblAssetCardService;
	@Autowired
	private ITblAssetNoService iTblAssetNoService;
	@Autowired
	private ICmpService iCmpService;

	@Operation(summary = "上架数量")
	@GetMapping("/queryPutOn")
	public ApiResult<Long> queryPutOn(String uid) {
		log.info("/api/nft/asset/queryPutOn uid:{}", uid);
		Long queryPutOn = iTblAssetService.queryPutOn(uid);
		return ApiResult.ok(queryPutOn);
	}

	@Operation(summary = "是否有365礼盒")
	@GetMapping("/hasGift365")
	public ApiResult<Boolean> hasGift365(Long appUid) {
		log.info("/api/nft/asset/hasGift365 appUid:{}", appUid);
		boolean hasGift365 = iTblAssetAccountService.hasGift365(appUid);
		return ApiResult.ok(hasGift365);
	}

	/**
	 * 批量查资产的所有详情信息 根据goodsId
	 * 
	 * @param goodsIds
	 * @return
	 */
	@GetMapping("/batchInfo/goodsId")
	public ApiResult<Map<String, AssetAllInfoResponse>> batchInfoGoodsIds(@RequestParam("goodsId") Collection<String> goodsIds) {
		log.info("/api/asset/batchInfo/goodsId goodsIds:{}", JSONUtil.toJsonStr(goodsIds));
		Map<String, AssetAllInfoResponse> map = iTblAssetService.batchInfoGoodsIds(goodsIds);
		return ApiResult.ok(map);
	}

	/**
	 * 批量查资产的所有详情信息 根据assetId
	 * 
	 * @param assetIds
	 * @return
	 */
	@GetMapping("/batchInfo/assetId")
	public ApiResult<Map<Long, AssetAllInfoResponse>> batchInfoAssetId(@RequestParam("assetId") Collection<Long> assetIds) {
		log.info("/api/asset/batchInfo/assetId assetIds:{}", JSONUtil.toJsonStr(assetIds));
		Map<Long, AssetAllInfoResponse> map = iTblAssetService.batchInfoAssetId(assetIds);
		return ApiResult.ok(map);
	}

	/**
	 * 查资产的所有详情信息 根据goodsId
	 * 
	 * @param assetId
	 * @return
	 */
	@GetMapping("/info/goodsId")
	public ApiResult<AssetAllInfoResponse> infoGoodsId(@RequestParam("goodsId") String goodsId) {
		log.info("/api/asset/info/goodsId goodsId:{}", goodsId);
		AssetAllInfoResponse response = iTblAssetService.infoWithGoodsId(goodsId);
		return ApiResult.ok(response);
	}

	/**
	 * 查资产的所有详情信息 根据assetId
	 * 
	 * @param assetId
	 * @return
	 */
	@GetMapping("/info/assetId")
	public ApiResult<AssetAllInfoResponse> infoAssetId(@RequestParam("assetId") Long assetId) {
		log.info("/api/asset/info/assetId assetId:{}", assetId);
		AssetAllInfoResponse response = iTblAssetService.infoWithAssetId(assetId);
		return ApiResult.ok(response);
	}

	@GetMapping("/queryAssetType")
	public ApiResult<List<AssetVo>> queryAssetType(Integer currPage, String uid, AssetTypeEnum type) {
		log.info("/api/asset/queryAssetType currPage:{},uid:{},type:{}", currPage, uid, type);
		List<AssetVo> queryAssetType = iTblAssetService.queryAssetType(currPage, uid, type);
		return ApiResult.ok(queryAssetType);
	}

	@GetMapping("/queryBlindBoxDetail")
	public ApiResult<List<BlindBoxDetailResponse>> queryBlindBoxDetail(List<String> goodsId) {
		log.info("/api/asset/queryAssetType goodsId:{}", JSONUtil.toJsonStr(goodsId));
		List<BlindBoxDetailResponse> response = iTblBlindBoxDetailService.queryBlindBoxDetail(goodsId);
		return ApiResult.ok(response);
	}

	/**
	 * 查询用户最条一次配置
	 * 
	 * @param assetId
	 * @return
	 */
	@GetMapping("/lastConfig")
	public ApiResult<AssetUserLogResponse> lastConfig(Long assetId) {
		TblAssetUserLog lastConfig = iTblAssetUserLogService.lastConfig(assetId);
		AssetUserLogResponse transfor = DozerUtil.transfor(lastConfig, AssetUserLogResponse.class);
		return ApiResult.ok(transfor);
	}

	@PostMapping("/saveUpChainFlag")
	public ApiResult<Boolean> saveUpChainFlag(String appUid, Long businessRefId) {
		log.info("/api/asset/saveUpChainFlag appUid:{},businessRefId:{}", appUid, businessRefId);
		Boolean result = iTblAssetExtService.saveUpChainFlag(appUid, businessRefId);
		return ApiResult.ok(result);
	}

	@Operation(summary = "玫瑰花销量统计")
	@PostMapping("/adjustPopularityRate")
	public ApiResult<Boolean> adjustPopularityRate(String goodsId, int targetValue) {
		log.info("/api/nft/asset/adjustPopularityRate goodsId:{},targetValue:{}", goodsId, targetValue);
		Boolean result = iTblAssetService.adjustPopularityRate(goodsId, targetValue);
		return ApiResult.ok(result);
	}

	@Operation(summary = "三方订单")
	@PostMapping("/thirdOrder")
	public ApiResult<MintResponse> thirdOrder(@RequestBody ThirdOrderRequest request) {
		log.info("/api/nft/asset/thirdOrder body:{}", JSONUtil.toJsonStr(request));
		BusinessAttachVo businessAttach = BusinessAttachVo.builder().assetId(Longs.tryParse(request.getConfigId())).goodsId(request.getConfigId()).build();
		TblPayOrderDto payOrderDto = TblPayOrderDto
				.builder()
				.appUserId(request.getAppUserId())
				.businessRefId(request.getConfigId())
				.businessAttach(JSONUtil.toJsonStr(businessAttach))
				.build();
		MintResponse rosePayAfter = iRoseService.rosePayAfter(payOrderDto, true);
		return ApiResult.ok(rosePayAfter);
	}

	@Operation(summary = "创建交易")
	@PostMapping("/transaction/makeTransaction")
	public ApiResult<TblAssetTransaction> makeTransaction(@RequestHeader("uid") String uid, @RequestBody @Valid MakeTransactionRequest makeOrder) {
		log.info("/api/nft/asset/transaction/makeTransaction param:{}", JSONUtil.toJsonStr(makeOrder));
		TblAssetTransaction makeTransaction = iNftService.makeTransaction(makeOrder);
		return ApiResult.ok(makeTransaction);
	}

	@Operation(summary = "取消交易")
	@PostMapping("/transaction/cancelTransaction")
	public ApiResult<CancelOrderResponse> cancelTransaction(@RequestHeader("uid") String uid,
			@RequestBody @Valid CancelTransactionRequest cancelTransactionRequest) {
		log.info("/api/nft/asset/transaction/cancelTransaction param:{}", JSONUtil.toJsonStr(cancelTransactionRequest));
		CancelOrderResponse cancelTransaction = iNftService.cancelTransaction(cancelTransactionRequest);
		return ApiResult.ok(cancelTransaction);
	}

	@Operation(summary = "确认交易")
	@PostMapping("/transaction/confirmTransaction")
	public ApiResult<ConfirmOrderResponse> confirmTransaction(@RequestHeader("uid") String uid,
			@RequestBody @Valid ConfirmTransactionRequest confirmTransactionRequest) {
		log.info("/api/nft/asset/transaction/cancelTransaction param:{}", JSONUtil.toJsonStr(confirmTransactionRequest));
		ConfirmOrderResponse cancelTransaction = iNftService.confirmTransaction(confirmTransactionRequest);
		return ApiResult.ok(cancelTransaction);
	}

	@Operation(summary = "风格使用次数统计")
	@GetMapping("/collection/statis")
	public ApiResult<Map<Long, Long>> collectionStatis() {
		log.info("/api/nft/asset/collection/statis ");
		BoundHashOperations<String, Long, Long> boundHashOps = stringRedisTemplate.boundHashOps("nft:collection:statis");
		Set<Long> keys = boundHashOps.keys();
		HashMap<Long, Long> newHashMap = Maps.newHashMap();
		keys.forEach(k -> {
			newHashMap.put(k, boundHashOps.get(k));
		});
		return ApiResult.ok(newHashMap);
	}

	@Operation(summary = "查询资产扩展信息")
	@GetMapping("/ext/infoWithAssetId")
	public ApiResult<AssetExtInfoResponse> assetExtInfoWithAssetId(Long assetId) {
		log.info("/api/nft/asset/ext/infoWithAssetId assetId:{}", assetId);
		AssetExtInfoResponse response = iTblAssetExtService.queryAssetExtInfoResponseInfo(assetId);
		return ApiResult.ok(response);
	}

	@Operation(summary = "查询资产扩展信息")
	@GetMapping("/assetCard/getUserCardInfo")
	public ApiResult<List<TblAssetCardDto>> getUserCardInfo(CardInfoRequest cardInfoRequest) {
		log.info("/api/nft/asset/assetCard/getUserCardInfo assetId:{}", JSONUtil.toJsonStr(cardInfoRequest));
		List<TblAssetCard> response = iTblAssetCardService.getUserCardInfo(cardInfoRequest);
		List<TblAssetCardDto> transforList = DozerUtil.transforList(response, TblAssetCardDto.class);
		return ApiResult.ok(transforList);
	}

	@Operation(summary = "查询卡片信息")
	@GetMapping("/card/assetNoInfoWithNoId")
	public ApiResult<AssetNoResponse> assetNoInfoWithNoId(Long noId) {
		log.info("/api/nft/asset/card/infoWithAssetId noId:{}", noId);
		AssetNoResponse response = iTblAssetNoService.assetNoInfoWithNoId(noId);
		return ApiResult.ok(response);
	}

	@Operation(summary = "资产详情")
	@GetMapping("/detailInfo")
	public ApiResult<AssetDetailInfo> detailInfo(String uid, String goodsId, Long accountId) {
		log.info("/api/nft/asset/detailInfo goodsId:{},accountId:{}", goodsId, accountId);
		AssetDetailInfo response = iTblAssetService.detailInfo(uid, goodsId, accountId);
		return ApiResult.ok(response);
	}

	@Operation(summary = "权益兑换划转资产")
	@PostMapping("/deliver")
	public ApiResult<Boolean> deliver(@RequestBody @Valid DeliverRequest deliverRequest) {
		log.info("/api/nft/asset/deliver request:{}", JSONUtil.toJsonStr(deliverRequest));
		Boolean deliver = iCmpService.deliver(deliverRequest);
		return ApiResult.ok(deliver);
	}
}
